import numpy as np
import matplotlib.pyplot as plt

def cal_dis(line_point1, line_point2, point):
    '''
        计算点到直线的距离
    :param line_point1: 直线上其中一点
    :param line_point2: 直线上另一点
    :param point: 待计算距离点
    :return: 距离
    '''

    # 对于两点坐标为同一点时,返回点与点的距离
    # print("line_point1", line_point1)
    # print("line_point2", line_point2)
    # if line_point1 == line_point2:
    #     point_array = np.array(point)
    #     point1_array = np.array(line_point1)
    #     return np.linalg.norm(point_array - point1_array)
    # 计算直线的三个参数
    A = line_point2[1] - line_point1[1]
    B = line_point1[0] - line_point2[0]
    C = (line_point1[1] - line_point2[1]) * line_point1[0] + \
        (line_point2[0] - line_point1[0]) * line_point1[1]

    # 根据点到直线的距离公式计算距离
    distance1 = np.abs(A * point[0] + B * point[1] + C) / (np.sqrt(A ** 2 + B ** 2))

    # 计算投影点
    X = point[0] - A * (A * point[0] + B * point[1] + C) / (A * A + B * B)
    Y = point[1] - B * (A * point[0] + B * point[1] + C) / (A * A + B * B)

    # 计算投影点到线段左侧点的距离
    distance2 = np.sqrt((X - line_point1[0]) ** 2 + (Y - line_point1[1]) ** 2)

    if Y > point[1]:
        distance1 = -distance1

    return distance1, distance2


def translation(ordinates):
    '''
        将机翼坐标整体平移到x坐标轴上
        归一化
    :param ordinates:
    :return:
    '''

    ordinates_trans = np.empty_like(ordinates)
    # 得到机翼最左（右）侧的点
    line1_id = np.argmin(ordinates[:, 0])  # 左（在附近找最佳点）
    line2_id = np.argmax(ordinates[:, 0])  # 右

    # 往上
    # while True:
    #     k, b = calK(ordinates[line1_id], ordinates[line2_id])
    #     flag = pointInOrOut(k, b, ordinates[line1_id - 1])
    #     if flag:
    #         break
    #     else:
    #         line1_id -= 1
    #         # print("line1_id:", line1_id)

    # 往下
    # while True:
    #     k, b = calK(ordinates[line1_id], ordinates[line2_id])
    #     flag = pointInOrOut(k, b, ordinates[line1_id + 1])
    #     if flag:
    #         break
    #     else:
    #         line1_id += 1
            # print("line1_id:", line1_id)

    # flag = 1000
    # while True:
    #     k, b = calK(ordinates[line1_id], ordinates[line2_id])
    #     flag1 = pointInOrOut(k, b, ordinates[line1_id - 1])
    #     flag2 = pointInOrOut(k, b, ordinates[line1_id + 1])
    #     if flag1 and flag2:
    #         break
    #     elif flag == 0:
    #         break
    #     elif flag1 and not flag2:
    #         line1_id += 1
    #         flag -= 1
    #         print("line1_id+:", line1_id)
    #     elif not flag1 and flag2:
    #         line1_id -= 1
    #         flag -= 1
    #         print("line1_id-:", line1_id)

    line1_point = ordinates[line1_id]
    line2_point = ordinates[line2_id]

    #
    k, b = calK(line1_point, line2_point)

    # show
    x = np.arange(-0.001, 0.1, 0.0002)
    plt.scatter(line1_point[0], line1_point[1], c='black')
    plt.plot([line1_point[0], line2_point[0]], [line1_point[1], line2_point[1]])
    plt.plot(x, k * x + b)

    # 遍历机翼中的每个点
    for i, ordinate in enumerate(ordinates):
        dis1, dis2 = cal_dis(line1_point,
                             line2_point,
                             ordinate)
        ordinates_trans[i] = np.asarray([dis2, dis1])

    # 归一化
    # normalize low;值得注意的是，下表面横坐标最小值不为0
    min = np.min(ordinates_trans[:, 0])
    max = np.max(ordinates_trans[:, 0])
    ordinates_trans[:, 0] = (ordinates_trans[:, 0] - min) / (max - min)

    return ordinates_trans


def calK(line_point1, line_point2):
    '''
        计算与line_point1和line_point2所在线段垂直的直线方程
    :param line_point1: 该点作垂线
    :param line_point2:
    :return:
    '''
    k = (line_point2[1] - line_point1[1]) / (line_point2[0] - line_point1[0])
    k = -1 / k
    b = -k * line_point1[0] + line_point1[1]
    return k, b


def pointInOrOut(k, b, point):
    '''

    :param k:
    :param b:
    :param point:
    :return:
    '''

    return (k * point[0] + b - point[1]) > 0

# test
# k, b = calK([1, 1], [2, 0])
# print(k, b)
# flag = pointInOrOut(k, b, [1, 2])
# print(flag)
